//
//  CoGeMissingsSearchController.m
//  CoGeOpenSource
//
//  Created by Tamas Nagy on 5/10/11.
//  Copyright 2011 home. All rights reserved.
//

#import "CoGeMissingsSearchController.h"


@implementation CoGeMissingsSearchController

@synthesize window;
@synthesize theTableView;
@synthesize progressIndicator;
@synthesize currentLabel;
@synthesize missingsDict;
@synthesize needsSkip;
@synthesize searchStarted;
@synthesize origDict;
@synthesize searchScopes;
@synthesize spotlightSearchButton;
@synthesize modalSession;

- (id)init
{
    self = [super init];
    if (self) {
        [theTableView setDelegate:self];
        
        CoGeThreadSafeMutableDictionary *tempDict = [[CoGeThreadSafeMutableDictionary alloc] init];
        CoGeThreadSafeMutableDictionary *tempMutDict = [[CoGeThreadSafeMutableDictionary alloc] init];
        
        self.missingsDict = tempDict;
        self.origDict = tempMutDict;
        
        [tempDict release];
        [tempMutDict release];
        
        //the app directory
        NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
        NSMutableArray *pathArray = [NSMutableArray arrayWithArray:[bundlePath componentsSeparatedByString:@"/"]];
        [pathArray removeLastObject];
        
        CoGeThreadSafeMutableArray *tempMutArray = [[CoGeThreadSafeMutableArray alloc] initWithObjects:[pathArray componentsJoinedByString:@"/"], NSMetadataQueryUserHomeScope, NSMetadataQueryLocalComputerScope, nil];

        self.searchScopes = tempMutArray;
        
        [tempMutArray release];
        
        keysToSkip = [[NSDictionary alloc] initWithObjectsAndKeys:@"skip", @"fakeTitle", 
                      @"skip",@"APSPlayers",
                      @"skip",@"UID",
                      @"skip",@"apsUIDs",
                      @"skip",@"ButtonTitle",
                      @"skip",@"modulPath",
                      @"skip",@"SliderSelectedPath",
                      @"skip",@"SliderSyncFallbackQCPatch",
                      @"skip",@"fallbackPath",
                      @"skip",@"modulview-qcPlayerModuleNameIfQC",
                      @"skip",@"",
                      nil];
    }
    
    return self;
}

- (void)dealloc
{
    [theTableView setDelegate:nil];
    [missingsDict release];
    [origDict release];
    [searchScopes release];
    [super dealloc];
}

#pragma mark Checking

-(BOOL)seemsToBeAFilePath:(NSString *)_string {

    return ([_string rangeOfString:@"/"].location != NSNotFound) && ([_string rangeOfString:@"."].location != NSNotFound) && ([_string rangeOfString:@"http://"].location == NSNotFound) && ([_string rangeOfString:@"https://"].location == NSNotFound);
    
}

-(void)searchFilePatchesInDict:(NSDictionary *)dict {

    for (NSString *curKey in [dict allKeys]) {
        
        id anObject = [dict objectForKey:curKey];
        
        if ((([keysToSkip objectForKey:curKey] == nil) && ([curKey rangeOfString:@"-usedFilePath"].location == NSNotFound)) && ([curKey rangeOfString:@"-qcplayerpath"].location == NSNotFound)) {
 
            if ([anObject isKindOfClass:[NSString class]]) {
                
                if ([self seemsToBeAFilePath:anObject]) {
                    
                    if (![[NSFileManager defaultManager] fileExistsAtPath:anObject]) {
                        
                  //      NSLog(@"found missing item: %@", anObject);
                        
                        [self.missingsDict setObject:anObject forKey:anObject];
                    }
                    
                    
                }
                
            } else {
                
                if ([anObject isKindOfClass:[NSDictionary class]]) {
                    
                    [self searchFilePatchesInDict:anObject];
                }
            }

        }
        
    }
    
}

-(BOOL)checkDictionary:(NSDictionary *)dict {
    
    NSLog(@"start search for missing files...");
    
    [[dict retain] autorelease];

    CoGeThreadSafeMutableDictionary *tempDict = [[CoGeThreadSafeMutableDictionary alloc] init];
    
    CoGeThreadSafeMutableDictionary *tempMutDict = [[CoGeThreadSafeMutableDictionary alloc] initWithDictionary:[[dict copy] autorelease]];
    
    self.origDict = tempMutDict;
    
    [tempMutDict release];
    
    CoGeThreadSafeMutableDictionary *tempDict2 = [[CoGeThreadSafeMutableDictionary alloc] initWithCapacity:0];
    
    self.missingsDict = tempDict2;
    [tempDict2 release];
    [tempDict release];
    
    [self searchFilePatchesInDict:self.origDict];
    
     
    if ([self.missingsDict count]>0) {
        NSLog(@"... found missing files!");
        [self.theTableView reloadData];
        self.modalSession = [NSApp beginModalSessionForWindow:self.window];
        [self.window setLevel:NSNormalWindowLevel+1];
        [self.theTableView reloadData];
        return YES;
    } else {
        NSLog(@"... no missing files");
        NSDictionary *returnDict = [[NSDictionary alloc] initWithDictionary:[[self.origDict copy] autorelease]];
        self.origDict = nil;
        
        [[NSNotificationCenter defaultCenter] postNotificationName:@"SpotlightSearchFinished" object:[returnDict autorelease]];

        return NO;
    }

}

#pragma mark Searching


-(void)spotlightSearchForFiles {
    
    NSMetadataQuery *query = nil;
    
    [self.progressIndicator startAnimation:self];
    
    self.searchStarted = YES;
    
    for (NSString *aKey in [self.missingsDict allKeys]) {
                
        query = [[NSMetadataQuery alloc] init];
                
        [query setSearchScopes:self.searchScopes];
        
        
        NSString *currentsearch = [[self.missingsDict objectForKey:aKey] lastPathComponent];
        
        //searching for display name is seems to be much faster then anything else!
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"kMDItemDisplayName == %@", currentsearch];
                 
        [query setPredicate:predicate];
        
        NSSortDescriptor *sortKeys=[[[NSSortDescriptor alloc] initWithKey:(id)kMDItemFSName
                                                                ascending:YES] autorelease];
        [query setSortDescriptors:[NSArray arrayWithObject:sortKeys]];
        
        if ([query startQuery])  {
            [[self.currentLabel cell] setTitle:[NSString stringWithFormat:@"Please wait, searching for: %@", currentsearch]];
            while (([query isGathering] && !self.needsSkip) && ([[query results] count] == 0))  {
                [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
            }
        }
        
        if (self.needsSkip) {
            [[currentLabel cell] setTitle:@"Search skipped."];
            [query stopQuery];
            [query release];
            
            
            break;
        }
        
        if ([query resultCount]>0) {
            [self.missingsDict setObject:[[query resultAtIndex:0] valueForAttribute:@"kMDItemPath"] forKey:aKey];
            [theTableView reloadData];

        }
        
        [query stopQuery];
        [query release];
    }
    
    [self.progressIndicator stopAnimation:self];
    [[self.currentLabel cell] setTitle:@""];
        
    [self.theTableView reloadData];
    
    self.needsSkip = NO;
    self.searchStarted = NO;
    [self.spotlightSearchButton setEnabled:YES];
}

#pragma mark Build final dict 

-(void)recursiveRebuildOfDict:(id)aDict skipItems:(BOOL)_skip {
    
    NSDictionary *workdict = [[NSDictionary alloc] initWithDictionary:[[aDict copy] autorelease]];
    
    for (NSString *currentKey in [workdict allKeys]) {
        
        id anObject = [aDict objectForKey:currentKey];
        
        if ([anObject isKindOfClass:[NSString class]]) {
            
            if ([self.missingsDict objectForKey:anObject] != nil) {
            
                if (!([[self.missingsDict objectForKey:anObject] isEqualToString:anObject])) {
                    
                    [aDict setObject:[self.missingsDict objectForKey:anObject] forKey:currentKey];
                
                } else {
                    
                    //if skip enabled, we "delete" the current value
                    if (_skip) {
                        
                        [aDict setObject:@"" forKey:currentKey];
                        
                    } else {
                        
                        //if no skip, we do nothing
                    }
                }
                
            }
            
            
        } else {
            
            if ([anObject isKindOfClass:[NSDictionary class]]) {
                
                [self recursiveRebuildOfDict:anObject skipItems:_skip];
            }
        }
    }
    
    [workdict release];
    
}


-(void)buildFinalDictAndSkipItem:(BOOL)_skip {

    [self recursiveRebuildOfDict:self.origDict skipItems:YES];
    
    
    NSDictionary *returnDict = [[NSDictionary alloc] initWithDictionary:self.origDict];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"SpotlightSearchFinished" object:returnDict];

    [returnDict release];
    self.origDict = nil;

    [NSApp endModalSession:self.modalSession];
    [self.window orderOut:self];
    
    
    

}

#pragma mark Skipping

-(IBAction)skipSpotlightSearch:(id)sender {
    
    if (!self.searchStarted) {
        
        //removes all the missing keys
        for (NSString *removeKey in [self.missingsDict allKeys]) {
            [self.missingsDict setObject:[NSString stringWithString:@""] forKey:removeKey];
        }
        
        [self buildFinalDictAndSkipItem:YES];
        

    } else {
        self.needsSkip = YES;
        
        [self.spotlightSearchButton setEnabled:YES];

    }


    
}

-(IBAction)doneSearch:(id)sender {
    
    if (!self.searchStarted) {

    } else {
        self.needsSkip = YES;
    }


    [self buildFinalDictAndSkipItem:NO];

}


#pragma mark Actions

-(void)manualLocate:(id)sender {
    
    NSOpenPanel *oPanel = [NSOpenPanel openPanel];
	
	NSInteger returnCode = [oPanel runModalForDirectory:nil file:nil types:nil];
	
	if (returnCode == NSOKButton) {
		
		NSArray *urls = [oPanel URLs];
		
		[self.missingsDict setObject:[[urls objectAtIndex:0] path] forKey:[[self.missingsDict allKeys] objectAtIndex:[theTableView selectedRow]]];
		
        [theTableView reloadData];
	}

    
}

-(IBAction)searchWithSpotlight:(id)sender {
    
    self.needsSkip = NO;
    
    [self.spotlightSearchButton setEnabled:NO];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        [self startSearchOnThread];
    });
    
}


-(void)startSearchOnThread {
    
    [self performSelector:@selector(spotlightSearchForFiles)];
}


#pragma mark TableView delegates

- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{
	
	
	return [self.missingsDict count];
	
}

- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{
	
    NSDictionary *tempMissingsDict = [NSDictionary dictionaryWithDictionary:[[self.missingsDict copy] autorelease]];
    
    
    if ([[tempMissingsDict allValues] count] == 0) {
        return nil;
    }
    
    //name
    if ([[tableColumn identifier] intValue] == 0) {
        return [[[tempMissingsDict allKeys] objectAtIndex:row] lastPathComponent];
    }
 
    //old path
    if ([[tableColumn identifier] intValue] == 1) {
        return [[tempMissingsDict allKeys] objectAtIndex:row];
    }

    //new path
    if ([[tableColumn identifier] intValue] == 2) {
        
        if ([[[tempMissingsDict allValues] objectAtIndex:row] isEqualToString:[[tempMissingsDict allKeys] objectAtIndex:row]]) {
        
            return nil;
            
        } else {
        
            return [[tempMissingsDict allValues] objectAtIndex:row];
        }
        
    }
    
    if ([[tableColumn identifier] intValue] == 3) {
        NSButtonCell *theCell = [tableColumn dataCellForRow:row];
        [theCell setTarget:self];
        [theCell setAction:@selector(manualLocate:)];
        return theCell;
        
    }
    
    return nil;
    
}



@end
